﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Assets.Scripts.Utility;

//Ljj 2019.6.11
//士兵单位的工厂类以及管理类，负责创建维护删除和提供索引查找
public class SoldierManager : MonoBehaviour
{
    public GameObject SoldierPrefab;
    public RandomGenerator mRandom;
    public static SoldierManager Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = GameObject.FindObjectOfType<SoldierManager>();
            }
            if (!_Instance)
            {
                GameObject obj = new GameObject("SoldierManager");
                _Instance = obj.AddComponent<SoldierManager>();
            }
            return _Instance;
        }
        set
        {
            _Instance = value;
        }
    }
    private static SoldierManager _Instance;

    private CSVData soldierInfo;


    public GameObject CreateSoldier(int index)
    {
        SoldierData soldierData = new SoldierData();
        soldierData.name = index;
        soldierData.hp = soldierData.damage = soldierData.attackSpeed = soldierData.walkSpeed = 1;
        soldierData.score = 0;
        return CreateSoldier(soldierData);
    }

    public GameObject CreateSoldier(SoldierData soldierData)
    {
        //Debug.Log(soldierData.name.ToString() + " " + soldierData.hp.ToString() + " " + soldierData.damage.ToString() + " " + soldierData.attackSpeed.ToString() + " " + soldierData.walkSpeed.ToString());
        if (soldierInfo == null)
            soldierInfo = new CSVData("Data/SoldierInfo");
        if (soldierData == null)
            return null;
        int index = soldierData.name;
        string name = soldierInfo.getData(index, "Name");
        Vector3 offset = new Vector3(RandomGenerator.Instance.Next(10) / 100.0f - 0.05f,
            RandomGenerator.Instance.Next(10) / 100.0f - 0.05f,
            0.0f);
        Vector3 pos = Function.LogicPosToWorldPos(ConstOfMap.initEnterPos);
        pos += offset;
        pos.x = (ConstOfMap.initEnterPos.x - 0.4f) * ConstOfMap.xGap;
        pos.z = pos.y * 0.1f;

        GameObject obj = GameObject.Instantiate(SoldierPrefab, pos, Quaternion.identity, transform);
        obj.layer = LayerMask.NameToLayer("Enemy");
        obj.AddComponent<RoadSelector>();

        Animator animator = obj.AddComponent<Animator>();
        AnimatorOverrideController overrideController = new AnimatorOverrideController();
        overrideController.runtimeAnimatorController =
            Resources.Load<RuntimeAnimatorController>("Animator/AnimatorController");
        animator.runtimeAnimatorController = overrideController;
        string soldierID = soldierInfo.getData(index, "ID");
        obj.name = soldierID;
        string animatorPath = "Animator/Soldier/" + soldierID + '/';
        for (int i = 0; i < ConstOfAnimator.AnimatorType.Length; i++)
        {
            string animatorType = ConstOfAnimator.AnimatorType[i];
            string animationClipPath = animatorPath + "Soldier_" + soldierID + "_" + animatorType;
            AnimationClip clip = Resources.Load<AnimationClip>(animationClipPath);
            if (clip != null) 
                overrideController[animatorType + "EmptyAnimator"] = clip;
        }
        Resources.UnloadUnusedAssets();

        BattleObject battle = obj.AddComponent<BattleObject>();
        float maxhp = float.Parse(soldierInfo.getData(index, "MaxHP"));
        float damage = float.Parse(soldierInfo.getData(index, "Damage"));
        float attackSpeed = 1f;
        float walkSpeed = float.Parse(soldierInfo.getData(index, "Speed"));
        if (soldierData != null)
        {
            battle.soldierData = soldierData;
            maxhp *= soldierData.hp;
            damage *= soldierData.damage;
            attackSpeed *= soldierData.attackSpeed;
            walkSpeed *= soldierData.walkSpeed;
        }
        battle.battleObjectName = soldierInfo.getData(index, "Name");
        battle.searchRange = float.Parse(soldierInfo.getData(index, "Range"));
        battle.setEnemy();
        battle.setMaxHP(maxhp);
        battle.setHP(maxhp);
        battle.damage = damage;
        battle.maxTargetCount = int.Parse(soldierInfo.getData(index, "MaxTarget"));

        battle.coolTime = float.Parse(soldierInfo.getData(index, "CoolTime")) / attackSpeed;
        battle.frontActionTime = float.Parse(soldierInfo.getData(index, "FrontActionTime")) / attackSpeed;
        battle.attackActionTime = float.Parse(soldierInfo.getData(index, "AttackActionTime")) / attackSpeed;
        battle.afterActionTime = float.Parse(soldierInfo.getData(index, "AfterActionTime")) / attackSpeed;
        battle.UpdateAnimatorSpeed();

        battle.attackNumber = int.Parse(soldierInfo.getData(index, "AttackNumber"));

        battle.stopWalkWhenLock = (soldierInfo.getData(index, "StopWalkWhenLock").Equals("TRUE"));

        string attackMode = soldierInfo.getData(index, "AttackMode");
        if (attackMode.Equals("Immediate"))
            battle.attackMode = AttackMode.Immediate;
        if (attackMode.Equals("Continued"))
            battle.attackMode = AttackMode.Continued;
        if (attackMode.Equals("Missile"))
        {
            battle.attackMode = AttackMode.Missile;
            battle.missilePrefab = Resources.Load<GameObject>(soldierInfo.getData(index, "MissilePrefab"));
            string[] missileOffset = soldierInfo.getData(index, "MissileOffset").Split(';');
            if (missileOffset.Length == 3)
                battle.missileOffset = new Vector3(float.Parse(missileOffset[0]), float.Parse(missileOffset[1]), float.Parse(missileOffset[2]));
        }
        if (attackMode.Equals("Parabola"))
        {
            battle.attackMode = AttackMode.Parabola;
            battle.parabolaPrefab = Resources.Load<GameObject>(soldierInfo.getData(index, "ParabolaPrefab"));
        }

        string attackEffectPrefab = soldierInfo.getData(index, "AttackEffectPrefab");
        if (!attackEffectPrefab.Equals(""))
            battle.attackEffectPrefab = Resources.Load<GameObject>(attackEffectPrefab);
        string hitEffectPrefab = soldierInfo.getData(index, "HitEffectPrefab");
        if (!hitEffectPrefab.Equals(""))
            battle.hitEffectPrefab = Resources.Load<GameObject>(hitEffectPrefab);

        battle.attackType = (AttackType)System.Enum.Parse(typeof(AttackType), soldierInfo.getData(index, "AttackType"));

        battle.aoeRange = float.Parse(soldierInfo.getData(index, "AoeRange"));

        Move move = obj.AddComponent<Move>();
        move.roadSelector = (Selector)System.Enum.Parse(typeof(Selector), soldierInfo.getData(index, "RoadSelector"));
        move.logicPos = ConstOfMap.initEnterPos;
        move.speed = walkSpeed;
        move.offset = offset;

        SoldierCatchGoal catchGoal = null;
        if (move.roadSelector != Selector.Player)
            catchGoal = obj.AddComponent<SoldierCatchGoal>();

        return obj;
    }

    public int NumOfSoldier()
    {
        if (soldierInfo == null)
        {
            soldierInfo = new CSVData("Data/SoldierInfo");
        }
        return soldierInfo.row;
    }
}